<template>
  <view class="sign-field">
    <view class="sign-left">电子签名:</view>
    <view class="sign-right" @tap="showSignNature">
      <text v-if="!successBaseUrl">点击签名</text>
      <image
        style="transform: rotate(-90deg); width: 200rpx; height: 500rpx"
        v-if="successBaseUrl"
        :src="successBaseUrl"
        mode="scaleToFill"
      />
    </view>
  </view>
  <canvas
    v-if="isShow"
    id="canvas"
    type="2d"
    class="canvas-main"
    @touchstart="touchStart"
    @touchend="touchEnd"
    @touchmove="touchMove"
    disable-scroll="true"
    style="width: 100%; height: 100%"
  >
    <view class="sign-content-btn horizontalScreen">
      <view class="clear-btn" @tap="clearCanvas">
        <text class="clear-info t-icon t-icon-clean"></text>
      </view>
      <view class="close-btn" @tap="closeCanvas">
        <text class="close-info t-icon t-icon-quxiao"></text>
      </view>
      <view class="sure-btn" @tap="signSuccess">确认</view>
    </view>
  </canvas>
</template>

<script setup="ts">
import { ref, getCurrentInstance, nextTick } from 'vue'
// 常量和状态
const instance = getCurrentInstance()
const isShow = ref(false) //是否显示签名
let canvas = null // canvas 实例
const pathArr = ref([]) // 用于存储触摸路径的数组
const isDraw = ref(false) // 状态：是否正在绘制
const canvasWidth = ref(0) //定义画布的宽度
const canvasheight = ref(0) //定义画布的高度
const canvasContext = ref(null) //canvas节点
const successBaseUrl = ref('') // 成功后图片的base64

const emit = defineEmits(['success'])
// 展示签名
const showSignNature = () => {
  isShow.value = true
  nextTick(() => {
    const query = uni.createSelectorQuery().in(instance)
    query
      .select('#canvas')
      .fields({ node: true, size: true })
      .exec((res) => {
        if (!res || !res[0]) return
        const { node, height, width } = res[0]
        try {
          const dpr = wx.getWindowInfo().pixelRatio
          canvas = node
          const ctx = canvas.getContext('2d')
          canvas.width = width * dpr
          canvas.height = height * dpr
          ctx.scale(dpr, dpr)
          canvasContext.value = ctx

          canvasWidth.value = width * dpr
          canvasheight.value = height * dpr
        } catch (error) {
          console.error('获取设备信息或设置canvas时发生错误:', error)
          // 根据项目需求，这里可以添加额外的错误处理逻辑
        }
      })
  })
}

// 开始绘制
const touchStart = (e) => {
  isDraw.value = true
  let { x, y } = e.touches[0]
  pathArr.value.push({ type: e.type, x: x, y: y })
  drawPath()
}

// 绘画移动
const touchMove = (e) => {
  e.preventDefault()
  if (!isDraw.value) return
  let { x, y } = e.touches[0]
  pathArr.value.push({ type: e.type, x: x, y: y })
  drawPath()
}
// 绘制路径
const drawPath = () => {
  const pathArrlength = pathArr.value.length
  if (!pathArrlength) return
  let startPoint, endPoint
  if (pathArr.value.length < 2) {
    startPoint = pathArr.value[pathArr.value.length - 1]
    endPoint = { x: startPoint.x + 1, y: startPoint.y }
  } else {
    startPoint = pathArr.value[pathArr.value.length - 2]
    endPoint = pathArr.value[pathArr.value.length - 1]
  }

  canvasContext.value.beginPath()
  canvasContext.value.lineCap = 'round'
  canvasContext.value.lineWidth = 10
  canvasContext.value.strokeStyle = '#000000' // 用于代替原来的 setStrokeStyle
  canvasContext.value.moveTo(startPoint.x, startPoint.y)
  canvasContext.value.lineTo(endPoint.x, endPoint.y)
  canvasContext.value.stroke()
}

// 绘画结束
const touchEnd = () => {
  isDraw.value = false
  pathArr.value = []
  canvasContext.value.closePath()
}

// 定义清空画布的函数
const clearCanvas = () => {
  // 关闭当前的路径
  // 清空路径数组
  pathArr.value.length = 0
  // 清空整个画布
  canvasContext.value.clearRect(0, 0, canvasWidth.value, canvasheight.value)
}

// 关闭画布
const closeCanvas = () => {
  isShow.value = false
  clearCanvas()
}

// 签名完成
const signSuccess = async () => {
  isShow.value = false
  successBaseUrl.value = await canvasToFilPath()
  emit('success', successBaseUrl.value)
}

// 保存签名
const canvasToFilPath = () => {
  return new Promise((resolve) => {
    uni.canvasToTempFilePath(
      {
        canvas: canvas,
        success: async (res) => {
          // 此处可以上传图片临时文件至服务器
          // console.log(res, 'res')
          const base64Url = await canvasToBase64(res.tempFilePath)
          resolve(base64Url)
        },
        fail: (err) => {
          console.log(err)
        },
      },
      instance,
    )
  })
}

// 图片转base64函数
const canvasToBase64 = (filePath) => {
  return new Promise((resolve, reject) => {
    let baseFormat = 'data:image/png;base64,'
    let base64 = wx.getFileSystemManager().readFileSync(filePath, 'base64')

    resolve(baseFormat + base64)
  })
}
</script>

<style lang="scss">
.sign-field {
  display: flex;
  .sign-left {
    font-weight: bold;
    padding-top: 80rpx;
  }
  .sign-right {
    background-color: #e1e1e1;
    margin: 10rpx 20rpx;
    height: 200rpx;
    flex: 1;
    border-radius: 10rpx;
    color: #4d4c4c;
    display: flex;
    justify-content: center;
    align-items: center;
  }
}
.canvas-main {
  background-color: #e6e6e6;
  height: 100%;
  width: 100%;
  position: fixed;
  top: 0;
  left: 0;
  .sign-content-btn {
    position: absolute;
    bottom: 0;
    right: 0;
    z-index: 50;
    display: flex;
    flex-direction: column;
    align-items: flex-end;
    .sure-btn {
      width: 150upx;
      height: 125upx;
      background-color: #0098fd;
      border-radius: 60upx 0 0 0;
      text-align: center;
      line-height: 125rpx;
      margin-bottom: -146rpx;
      color: #fff;
    }
    .clear-btn {
      margin: 20rpx;
      height: 100rpx;
      width: 100rpx;
      text-align: center;
      line-height: 125rpx;
      .clear-info {
        padding: 20rpx;
      }
    }
    .close-btn {
      margin: 20rpx;
      height: 100rpx;
      width: 100rpx;
      text-align: center;
      line-height: 125rpx;
      .close-info {
        padding: 20rpx;
      }
    }
  }
  .horizontalScreen {
    left: 0 !important;
    bottom: 0 !important;
    right: auto !important;
    transform: rotate(90deg);
    transform-origin: bottom right;
  }
}
</style>
